
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;




public class Advanced_Settings extends JFrame  implements ActionListener,WindowListener	{
	
	private volatile static Advanced_Settings einzigeInstanz;
	/**
	 * AntSimulation auf die sich das die AdvancedSettings beziehen
	 */
	private AntSimulation antSim;
	
	/**
	 * spezielle Slider zum Einstellen der Laenge der Barricaden bzw. der
	 * Ameisenperspective und der Futterstaerke mit festgelegten init-Werten
	 */
	private BarSlider jsPotency,jsDeg,jsPheroBord,jsWaitConst,jsFollowTr,
						jsPheroAll,jsVapDeg,jsVapVol,
						jsGettingOn,jsGettingDiff,jsHomeStep,jsFollowStep;
	
	/**
	 * Grundpanel, auf das die anderen Komponenten gelegt werden
	 */
	private JPanel jpGeneral;
	
	/**
	 * Insets fuer dynamische Gestaltung des Layouts
	 */
	private Insets iDefault;

	private JRadioButton jrStartAll, jrStartInt;
	
	private JComboBox jcbExactMode;
	
	private JButton jbApply,jbCancel,jbDefault,jbExit;
	
	
	/**
	 * Standardkonstruktor
	 * @param as die AntSimulation auf die sich das Fenster bezieht
	 */
	public Advanced_Settings(AntSimulation as){
		super("Ants - Advanced Settings");
		
		antSim=as;
	
		jpGeneral = new JPanel();
		
		iDefault=new Insets(2,2,4,2);
		initComponents();
			
		ButtonGroup bg =new ButtonGroup();
		bg.add(jrStartAll);
		bg.add(jrStartInt);
		
		readData();
		this.add(jpGeneral);
		this.addWindowListener(this);
		this.setLocation(0, 0);
		this.setResizable(false);		
		//this.setSize(new Dimension(480,750));
		this.pack();
		Start.setIcon(this);
	}//constructor
	
	public Advanced_Settings getInstanz(){
		
		if(einzigeInstanz==null){
			synchronized(Advanced_Settings.class){
				if(einzigeInstanz==null){
					einzigeInstanz=new Advanced_Settings(antSim);
				}
			}
		}
		einzigeInstanz.setVisible(true);
		
		return einzigeInstanz;
		
	}

	/**
	 * initialisiert die Gui-Komponenten auf dem Panel unter Zuhilfenahme des
	 * entsprechenden Layouts
	 */
	private void initComponents(){
	
		GridBagLayout gb = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		jpGeneral.setLayout(gb);
			
		c.anchor=GridBagConstraints.LINE_START;
		c.insets=iDefault;
		
		
		JLabel jlStartMode=new JLabel("start mode: ");
		gb.setConstraints(jlStartMode, c);
		jpGeneral.add(jlStartMode);
		
		JLabel jlAntsSets=new JLabel("ant settings");	
		jlAntsSets.setForeground(Color.red);
			c.gridy=2;
			gb.setConstraints(jlAntsSets, c);
			jpGeneral.add(jlAntsSets);
			
		JLabel jlDeg=new JLabel("perspective (degrees): ");
			c.gridy=3;
			gb.setConstraints(jlDeg, c);
			jpGeneral.add(jlDeg);
		
		JLabel jlAnthill=new JLabel("anthill perception: ");
			c.gridy=5;
			gb.setConstraints(jlAnthill, c);
			jpGeneral.add(jlAnthill);
		
		JLabel jlHomeStep=new JLabel("looking for home:");
			c.gridy=7;
			gb.setConstraints(jlHomeStep, c);
			jpGeneral.add(jlHomeStep);
		
		JLabel jlPheroBord=new JLabel("pheromone border: ");
			c.gridy=9;
			gb.setConstraints(jlPheroBord, c);
			jpGeneral.add(jlPheroBord);	
			
		JLabel jlWaitConst=new JLabel("wait constant: ");
			c.gridy=11;
			gb.setConstraints(jlWaitConst, c);
			jpGeneral.add(jlWaitConst);
		
		JLabel jlFolloTr=new JLabel("follow trail: ");
			c.gridy=13;
			gb.setConstraints(jlFolloTr, c);
			jpGeneral.add(jlFolloTr);
		
		JLabel jlFollowStep=new JLabel("pheromone testing:");
			c.gridy=15;
			gb.setConstraints(jlFollowStep, c);
			jpGeneral.add(jlFollowStep);
			
		JLabel jlGettingOn=new JLabel("getting on:");
			c.gridy=17;
			gb.setConstraints(jlGettingOn, c);
			jpGeneral.add(jlGettingOn);
		
		JLabel jlGettingDiff=new JLabel("covered distance:");
			c.gridy=19;
			gb.setConstraints(jlGettingDiff, c);
			jpGeneral.add(jlGettingDiff);
			
		JLabel jlPheroSets=new JLabel("pheromone settings");
			jlPheroSets.setForeground(Color.red);
			c.gridy=21;
			gb.setConstraints(jlPheroSets, c);
			jpGeneral.add(jlPheroSets);
				
		JLabel jlPotency = new JLabel("potency of food: ");
			c.gridy=22;		
			gb.setConstraints(jlPotency, c);
			jpGeneral.add(jlPotency);
						
		JLabel jlPheroAl=new JLabel("pheromones always left:");
			c.gridy=24;
			gb.setConstraints(jlPheroAl, c);
			jpGeneral.add(jlPheroAl);
		
		JLabel jlVapDeg=new JLabel("vaporisation degree: ");
			c.gridy=26;
			gb.setConstraints(jlVapDeg, c);
			jpGeneral.add(jlVapDeg);	
		
		JLabel jlVapVol=new JLabel("vaporisation volume:");
			c.gridy=28;
			gb.setConstraints(jlVapVol, c);
			jpGeneral.add(jlVapVol);	
			
		c.anchor=GridBagConstraints.CENTER;
		
		jrStartAll = new JRadioButton("all at once",true);
		c.gridy=1;
		c.gridx=1;
		c.gridwidth=3;
		gb.setConstraints(jrStartAll, c);
		jpGeneral.add(jrStartAll);
		
		jrStartInt= new JRadioButton("at intervalls",false);
		c.gridx=4;
		c.gridwidth=3;
		gb.setConstraints(jrStartInt, c);
		jpGeneral.add(jrStartInt);
		
		c.gridheight=2;
		jsDeg=new BarSlider(0,180,180,45);
			c.gridx=1;
			c.gridy=3;
			c.gridwidth=6;
			gb.setConstraints(jsDeg, c);
			jpGeneral.add(jsDeg);
		
		
		String [] rationals={"1/10","1/5","1/4","1/3","1/2","1"};
		jcbExactMode=new JComboBox(rationals);
		jcbExactMode.setPreferredSize(new Dimension(100,20));
		jcbExactMode.setSelectedIndex(3);
			c.gridy=5;
			gb.setConstraints(jcbExactMode, c);
			jpGeneral.add(jcbExactMode);
		
		jsHomeStep=new BarSlider(0,100,100,20,10);
			c.gridy=7;
			gb.setConstraints(jsHomeStep, c);
			jpGeneral.add(jsHomeStep);
	
		jsPheroBord=new BarSlider(20,100,40,20,10);//min ,max ,init, major tick
			c.gridy=9;
			gb.setConstraints(jsPheroBord, c);
			jpGeneral.add(jsPheroBord);
		
		jsWaitConst=new BarSlider(0,10,4,1);//min ,max ,init, major tick
			c.gridy=11;
			gb.setConstraints(jsWaitConst, c);
			jpGeneral.add(jsWaitConst);
		
		jsFollowTr=new BarSlider(0,10,4,5,1);//min ,max ,init, major tick
			c.gridy=13;
			gb.setConstraints(jsFollowTr, c);
			jpGeneral.add(jsFollowTr);
		
		jsFollowStep=new BarSlider(1,20,2,5,1);
			c.gridy=15;
			gb.setConstraints(jsFollowStep, c);
			jpGeneral.add(jsFollowStep);
			
		jsGettingOn=new BarSlider(1,20,10,5,1);
			c.gridy=17;
			gb.setConstraints(jsGettingOn, c);
			jpGeneral.add(jsGettingOn);
			
		jsGettingDiff=new BarSlider(1,20,6,5,1);
			c.gridy=19;
			gb.setConstraints(jsGettingDiff, c);
			jpGeneral.add(jsGettingDiff);	
		
		jsPotency = new BarSlider(20,100,30,20,5);//min max init major minor
			c.gridy=22;
			gb.setConstraints(jsPotency, c);
			jpGeneral.add(jsPotency);
				
		jsPheroAll=new BarSlider(0,40,1,10,1);//+16 bei auswertung wird zu nofood
			c.gridy=24;
			gb.setConstraints(jsPheroAll, c);
			jpGeneral.add(jsPheroAll);
			
		jsVapDeg=new BarSlider(10,100,80,20,5);//min ,max ,init, major tick
			c.gridy=26;
			gb.setConstraints(jsVapDeg, c);
			jpGeneral.add(jsVapDeg);
				
		jsVapVol=new BarSlider(0,30,5,5);
			c.gridy=28;
			gb.setConstraints(jsVapVol, c);
			jpGeneral.add(jsVapVol);

		Dimension dButton = new Dimension(150,20);
		c.anchor=GridBagConstraints.LINE_START;
	
		jbApply =new JButton("apply changes");
		jbApply.addActionListener(this);
		//jbApply.setPreferredSize(dButton);
		c.gridx=0;
		c.gridy=30;
		c.gridwidth=1;
		c.gridheight=1;
		gb.setConstraints(jbApply, c);
		jpGeneral.add(jbApply);
		
		jbCancel =new JButton("cancel");
		jbCancel.addActionListener(this);
		//jbCancel.setPreferredSize(dButton);
		c.gridx=1;
		c.gridwidth=2;
		//c.anchor=GridBagConstraints.LINE_END;
		gb.setConstraints(jbCancel, c);
		jpGeneral.add(jbCancel);
		
		jbDefault =new JButton("default");
		jbDefault.addActionListener(this);
		//jbDefault.setPreferredSize(dButton);
		c.gridx=3;
	//	c.anchor=GridBagConstraints.LINE_END;
		gb.setConstraints(jbDefault, c);
		jpGeneral.add(jbDefault);
		
		
		jbExit =new JButton("close");
		jbExit.addActionListener(this);
		//jbExit.setPreferredSize(dButton);
		c.gridx=5;
		gb.setConstraints(jbExit, c);
		jpGeneral.add(jbExit);
	}//initComponents()
	
	
	/**
	 * stellt die Defaultwerte fuer alle Regler ein
	 */
	private void setDefaultData(){
		jsDeg.setValue(180);
		jcbExactMode.setSelectedIndex(3);
		
		jsFollowTr.setValue(4);
		jsPheroAll.setValue(1);//+16 bei Auswertung
		jsPheroBord.setValue(40);
		
		jsPotency.setValue(30);
		jsVapDeg.setValue(80);
		jsWaitConst.setValue(4);
		
		jsHomeStep.setValue(100);
		jsGettingOn.setValue(10);
		jsGettingDiff.setValue(6);
		jsFollowStep.setValue(2);
		jsVapVol.setValue(5);
		
		jrStartAll.setSelected(true);
		
	}//setDefaultData
	
	/**
	 * liest die eingestellten Werte aus den Reglern aus und
	 * setzt die ensprechenden Parameter im Hauptprogramm
	 */
	
	private void getAndSetData(){
		
		//StartModus
		if(jrStartInt.isSelected()){
			antSim.setIntervallStart(true);
		}
		//Blickfeld der Ameise
		int deg=jsDeg.getValue()/45;
		deg++;
		Ant.setAngle(deg);
		
		//Tore des Ameisenhuegels
		int tmp=6-jcbExactMode.getSelectedIndex();
		if(tmp==6) tmp=10;
		Ant.setExactMode(tmp);
		
		
		//wie oft die nach-hause-richtung aktualisiert wird
		Ant.setActualizingHomeTimeStep(jsHomeStep.getValue());
		
		//PheromoneWahrnehmgrenze
		Ant.setBorderPheromones(jsPheroBord.getValue());
		
		//Wartezeit wenn ziel besetzt von ameise
		Ant.setWaitConstant(jsWaitConst.getValue());
		
		//Ab wann wird einer duftspur fuer 10 schritte gefolgt
		Ant.setQueuedCounterBorder(jsFollowTr.getValue());
		
		//wie oft nach duftspur gesucht wird
		Ant.setFollowingTimeStep(jsFollowStep.getValue());
		
		////wie oft vorankommen ueberprueft wird
		Ant.setGettingOnTimeStep(jsGettingOn.getValue());
		
		//wieviel die Ameise zurueckgelegt haben muss
		Ant.setGettingOnDiff(jsGettingDiff.getValue());
		
		//Potency des Futters
		if(	Ant.GOTFOOD!=jsPotency.getValue()){
			antSim.changeAllAntsGotFood(jsPotency.getValue());
			Ant.GOTFOOD=jsPotency.getValue();
		}
	
		
		
		//Ueberbleibsel von nofood
		if(Ant.NOFOOD!=(jsPheroAll.getValue()+16)){
			antSim.changeAllAntsNoFood(jsPheroAll.getValue()+16);
			Ant.NOFOOD=(jsPheroAll.getValue()+16);
		}
		
		//Verdunstungsgrad
		PheromoneTrail.foodfactor=jsVapDeg.getValue();
		
		//Wie viel verdunstet
		AntSimulation.vaporising=jsVapVol.getValue();
		
	}//getAndSetData
	
	/**
	 * liest die im Programm eingestellten Werte und setzt die Regler passend
	 */

	private void readData(){
		
		//StartModus
		if(	antSim.isIntervallStart()){
			jrStartInt.setSelected(true);
		}else{
			jrStartAll.setSelected(true);
		}
		
		//Blickfeld der Ameise
		int deg=Ant.getRangeAngle();
		deg--;
		jsDeg.setValue(45*deg);
				
		//Tore des Ameisenhuegels
		int tmp=Ant.getExactMod();
		if(tmp==10){
			jcbExactMode.setSelectedIndex(0);
		}else{
			jcbExactMode.setSelectedIndex(6-tmp);
		}
		
		//Anzahl der Aktualisierungen der Richtung auf Heimweg
		jsHomeStep.setValue(Ant.getActualizingHomeTimeStep());
		
		//PheromoneWahrnehmgrenze
		jsPheroBord.setValue(Ant.getBorderPheromone());
		
		//Wartezeit wenn ziel besetzt von ameise
		jsWaitConst.setValue(Ant.getWaitConstant());;
		
		//Ab wann wird einer duftspur fuer 10 schritte gefolgt
		jsFollowTr.setValue(Ant.getQueuedCounterBorder());
		
		//wie oft nach duftspur gesucht wird
		jsFollowStep.setValue(Ant.getFollowingTimeStep());
		
		////wie oft vorankommen ueberprueft wird
		jsGettingOn.setValue(Ant.getGettingOnTimeStep());
		
		//wieviel die Ameise zurueckgelegt haben muss
		jsGettingDiff.setValue(Ant.getGettingOnDiff());
		
		//Potency des Futters
		jsPotency.setValue(Ant.GOTFOOD);
	
		
		//Ueberbleibsel von nofood
		jsPheroAll.setValue(Ant.NOFOOD-16);
		
		//Verdunstungsgrad
		jsVapDeg.setValue(PheromoneTrail.foodfactor);
	}
	
	/**
	 * ActionListener
	 */
	public void actionPerformed(ActionEvent aEv) {
		Object source=aEv.getSource();
	
		if(source==jbExit){
			this.dispose();
		}
		else if (source==jbDefault){
			this.setDefaultData();
		}
		else if(source==jbCancel){
			this.readData();
		}else if(source==jbApply){
			if(jsGettingOn.getValue()<=jsGettingDiff.getValue()){
							JOptionPane.showMessageDialog(this,"Please set correct values for \"getting on\".\n" +
						"\"Covered Distance\" should not be higher than \"getting on\".");
			}
			else if(jsPotency.getValue()<=(jsPheroAll.getValue()+16)){
				JOptionPane.showMessageDialog(this,"Please set correct values.\nThe potency of food should be higher than the pheromones that are always left.");
			}else{
				this.getAndSetData();
			}
		}
	}//actionPerformed(ActionEvent aEv)



	
	public void windowActivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}



	
	public void windowClosed(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}



	
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		this.dispose();
		einzigeInstanz=null;
	}



	
	public void windowDeactivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}



	
	public void windowDeiconified(WindowEvent e) {
		
	}



	
	public void windowIconified(WindowEvent e) {
		
	}



	
	public void windowOpened(WindowEvent e) {

		
	}
	

	
}//class
